#include "parser.h"

#include <fstream>
#include <cstdlib>

using namespace xEngine::CoreSystem::Events;



// konstruktor
Parser::Parser() {
    this->scanner = new Scanner;
    this->scanner->nextToken();
}

void Parser::shutDown() {
    if ( this->scanner != NULL )
    {
        delete this->scanner;
        this->scanner = NULL;

        // TODO: inform the logging system
    }
}

void Parser::compileFile(char *file, SymTable<SceneNode*>  *objMap)
{

    // Preliminary check: objMap must be present
    if ( objMap == NULL )
        return;
    else
        this->objectsTab = objMap;

    this->g_Error = ""; // Set global error to zero

    this->symTab.clear();

    fstream scriptFile(file, fstream::in);

    if (!scriptFile.is_open()) {
        cout<< "Error opening script file."<<endl;
        return;
    }

   // Parser parser;
    string script;
    string line;
    bool p;

   // int line = 1;

    // Read script from file, store it into script string
    while (!scriptFile.eof())
    {
        getline(scriptFile, line); // Read line
        script += line; // Add line to script
    }

    p = this->parse(script); // Now parse script

        //      g_Error += "Error while compiling.\r\n";
    if (!p)
    {
        g_Error += "\r\n\r\nNOT SUCCESSFULL!\r\n";
       /*     g_Error = g_Error + "Error at line: ";
                        g_Error += line ;
                        g_Error += "r\n";
            break;*/


    }
    else
    g_Error += "\r\n\r\nSUCCESS!\r\n";

      //  line ++;



    g_Error += "\r\n------------ DONE -------------\r\n";

    scriptFile.close();

}

string Parser::getStatus() {
    return this->g_Error;
}



// parse, glavna metoda
bool Parser::parse(string line) {

    this->scanner->setInput(line);
    this->g_Error = "";

    // Do parsing
	return XSCRIPT() && this->scanner->currentToken().getEof();
}



bool Parser::XSCRIPT() {
    //::= begin BODY end
    if (scanner->currentToken().getLexem() == "begin")
    {
        scanner->nextToken();

        bool tmp = BODY();

        if (tmp && scanner->currentToken().getLexem() == "end") {
            scanner->nextToken();
            return true;
        }
        else
        {
            // must end with end error
            cout<<"Error: expected end token"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;

            return false;
        }
    }
    else
    {
        // must start with begin error
        cout<<"Error: Program should start with begin"<<endl;
        cout<<scanner->currentToken().getTokenInfo()<<endl;

    }

    return false;
}

bool Parser::BODY() {
    //::= LINE B
    return LINE() && B();
}

bool Parser::B() {
    //::= LINE B | ?

    if ( LINE() )
    {
        if ( B() )
            return true;
    }

    return true; // Empty derivation allowed.
}

bool Parser::LINE() {
    //::= def identificator = E | PART TRANSFORMATION

    TransformationData *transfData = NULL;
   // BODYPART part; // OBSOLETE
    string object; // Object we're transforming

    /// HERE
    if ( DEFVAR() ) // Do ve have an variable definition?
        return true;
    else if ( UPDATEVAR() ) // Do we have an variable update?
        return true;
    else if ( DEFOBJ() )
        return true;
    else if ( APPLY_FORCE() )
        return true;
    else if ( APPLY_LINEAR_VELOCITY() )
        return true;

    else if ( OBJECT(object) ) // Transformation ?
    {
        // Ok so far, we expect transformation now.
        //scanner->nextToken();

        if ( TRANSFORMATION(transfData) )
        {
            // OK
            // TRANSFORMATION EXECUTE SECTION
            //======================================================
            //

            if ( transfData->metaData == ROTATE ) {


                cout << endl<<"Rotate" <<endl;

                float *val = (float*)transfData->data;
                cout<<"angle: "<< *val <<endl;

                // Post event
                RotateEvent *rot =  new RotateEvent; //&EventSystem::getInstance().rotateEvent;
                rot->set(object, *val);

                EventSystem::getInstance().pushEvent(rot);
            }
            else if ( transfData->metaData == TRANSLATE ) {
                cout << endl <<"Translate" <<endl;

                Vector3 *vec = (Vector3*)transfData->data;
                cout<<"x, y, z: "<<vec->x<<' '<<vec->y<<' '<<vec->z<<' '<<endl;

                TranslateEvent *tr =  new TranslateEvent;
                tr->set(object, *vec);

                EventSystem::getInstance().pushEvent(tr);


            }

            cout<<object<<endl;


            //
            //=======================================================
            if (transfData != NULL) delete transfData; // Delete transformation data
            return true;
        }
        else
        {
            // Transformation expected error
            cout<<"Error: Transformation expected!"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
        }
    }

    if (transfData != NULL) delete transfData; // Delete transformation data if any

    return false;
}

//
// APPLY's
//
bool Parser::APPLY_FORCE() {
    if (scanner->currentToken().getLexem() == "force") {
        scanner->nextToken();

        Vector3 *vec = new Vector3;
        if ( VECTOR(vec) ) {

            if (scanner->currentToken().getLexem() == "at") {
                scanner->nextToken();
            }

            string objName = scanner->currentToken().getLexem();

            // Identificator, check for presence in table
            if ( this->objectsTab->containsSym(objName) )
            {
                // Post event!

                delete vec;
                scanner->nextToken();
                return true;
            }
            else
            {
                cout<<"Error, there is no object named "<<objName<<endl;
                cout<<scanner->currentToken().getTokenInfo()<<endl;
                return false;
            }

        }
        else
        {
            cout<<"Error, vector expected"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }

    }


    return false;
}

bool Parser::APPLY_LINEAR_VELOCITY() {
    if (scanner->currentToken().getLexem() == "linear_velocity") {
        scanner->nextToken();

        Vector3 *vec = new Vector3;
        if ( VECTOR(vec) ) {

            if (scanner->currentToken().getLexem() == "at") {
                scanner->nextToken();
            }

            string objName = scanner->currentToken().getLexem();

            // Identificator, check for presence in table
            if ( this->objectsTab->containsSym(objName) )
            {
                // Post event!

                delete vec;
                scanner->nextToken();
                return true;
            }
            else
            {
                cout<<"Error, there is no object named "<<objName<<endl;
                cout<<scanner->currentToken().getTokenInfo()<<endl;
                return false;
            }

        }
        else
        {
            cout<<"Error, vector expected"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }

    }


    return false;
}

//
// OBJECTS
//

bool Parser::DEFOBJ() {
    // DEFOBJ ::= def object object_id as OBJ_TYPE with OBJ_PROPERTIES at VECTOR
    Vector3 *vec = NULL;

    NewB2OEvent *event = NULL;


 //   if (scanner->currentToken().getLexem() == "def") {
 //       scanner->nextToken();

        if (scanner->currentToken().getLexem() == "object") {
            scanner->nextToken();
            event = new NewB2OEvent; // Create event

            // We expect here uniqe identificator (string). It shouldn't be in symtable yet.
            if ( scanner->currentToken().getType() == IDENTIFICATOR ) {
                // Ok, we have string, validate it.
                event->objName = scanner->currentToken().getLexem();
                scanner->nextToken();

                if (scanner->currentToken().getLexem() == "as") {
                    scanner->nextToken();

                    if ( OBJ_TYPE( event->phyType ) ) {
                        if (scanner->currentToken().getLexem() == "with") {
                            scanner->nextToken();
                        }

                            if ( OBJ_PROPERTIES( event->materialData, event->shapeData,
                                    event->visualData, event->shape, event->visual) )
                            {
                                if (scanner->currentToken().getLexem() == "at") {
                                    scanner->nextToken();

                                    vec = new Vector3(); // DELETE

                                    if ( VECTOR( vec ) ) {

                                        event->position = *vec;
                                        delete vec;

                                        this->objectsTab->insertSym( event->objName, NULL );

                                        EventSystem::getInstance().pushEvent(event);
                                        return true;
                                    }
                                }

                            }
                      //  }
                    }

                }

            }

        }

 //   }

    return false;
}


bool Parser::OBJ_TYPE(TYPE &objType) {
    // OBJ_TYPE ::= static | dynamic

    if (scanner->currentToken().getLexem() == "static") {
        // Ok
        scanner->nextToken();

        objType = STATIC;

        return true;
    }
    else if (scanner->currentToken().getLexem() == "dynamic") {
        // Ok
        scanner->nextToken();

        objType = DYNAMIC;
        
        return true;
    }

    return false;
}

bool Parser::OBJ_PROPERTIES( MaterialData &materialData, ShapeData &shapeData, VisualData &visualData, xEngine::CoreSystem::Events::SHAPE &shapeType, xEngine::CoreSystem::Events::VISUAL &visualType ) {
    // OBJ_PROPERTIES ::= MATERIAL SHAPE  VISUAL

    return MATERIAL(materialData) && SHAPE(shapeData, shapeType) && VISUAL(visualData, visualType);
}

/*
 *
 * 	bool MATERIAL(MaterialData &materialData);
	bool DENSITY(int &val);
	bool RESTITUTION(int &val);
	bool SHAPE(ShapeData &shapeData, SHAPE &shapeType);
	bool VISUAL(VisualData &visualData, VISUAL &visualType);
 */

bool Parser::MATERIAL(MaterialData &materialData) {
    // MATERIAL ::= material(DENSITY RESTITUTION) | material( set material_id ) |  e
    if ( scanner->currentToken().getLexem() == "material" ) {
        scanner->nextToken();

        if ( scanner->currentToken().getLexem() == "(" ) {
            scanner->nextToken();
            bool ok = DENSITY( materialData.density ) && RESTITUTION( materialData.restitution );

            if ( ok ) {
                if ( scanner->currentToken().getLexem() == ")" ) {
                    scanner->nextToken();
                    return true;
                }
            }
        }
        else {
            cout<<"Error, expected ("<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }
    }

    // Defaults
    materialData.density = 1.0f;
    materialData.restitution = 0.75f;

    return true;
}

bool Parser::DENSITY(float &val) {
    // DENSITY ::= density:E |  e


    if ( scanner->currentToken().getLexem() == "density" ) {
        scanner->nextToken();

        if ( scanner->currentToken().getLexem() == ":" ) {
            scanner->nextToken();

            return E(val); // F ?
        }
        else {
            cout<<"Error, expected :"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }

    }

    val = 1.0f;
    return true; // Empty derivation
}

bool Parser::RESTITUTION(float &val) {
    // RESTITUTION ::= restitution:E | e



    if ( scanner->currentToken().getLexem() == "restitution" ) {
        scanner->nextToken();

        if ( scanner->currentToken().getLexem() == ":" ) {
            scanner->nextToken();

            return E(val); // F ?
        }
        else {
            cout<<"Error, expected :"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }

    }

    val = 0.75f; // Default
    return true; // Empty derivation
}

bool Parser::SHAPE(ShapeData &shapeData, xEngine::CoreSystem::Events::SHAPE &shapeType) {
    // SHAPE ::= rectangle = (width:F height:F) | circle = radius:E | polygon = { VERTICES_LIST } |  e
    if ( scanner->currentToken().getLexem() == "rectangle" ) {
        scanner->nextToken();

        shapeType = RECT; // type

      //  if ( scanner->currentToken().getLexem() == "=" ) {
      //      scanner->nextToken();

            if ( scanner->currentToken().getLexem() == "(" ) {
                scanner->nextToken();

                if ( scanner->currentToken().getLexem() == "width" ) {
                    scanner->nextToken();

                    if ( scanner->currentToken().getLexem() == ":" ) {
                        scanner->nextToken();

                        if ( F( shapeData.w ) ) {

                            if ( scanner->currentToken().getLexem() == "height" ) {
                                scanner->nextToken();


                                 if ( scanner->currentToken().getLexem() == ":" ) {
                                    scanner->nextToken();

                                    if ( F( shapeData.h ) ) {

                                        if (scanner->currentToken().getLexem() == ")") {
                                            // OK
                                            scanner->nextToken();
                                            return true;
                                        }
                                        else {

                                            // Error
                                            cout<<"Error: expected ')' "<<endl;
                                            cout<<scanner->currentToken().getTokenInfo()<<endl;
                                            return false;
                                        }
                                    }
                                    else
                                        return false;

                                 }

                            }
                            else {
                                cout<<"Error: expected 'height' "<<endl;
                                cout<<scanner->currentToken().getTokenInfo()<<endl;
                                return false;
                            }


                        }
                        else
                            return false;
                    }
                    else {
                        // Error
                        cout<<"Error: expected ':' "<<endl;
                        cout<<scanner->currentToken().getTokenInfo()<<endl;
                        return false;
                    }

                }
                else {
                    // Error
                    cout<<"Error: expected 'width' "<<endl;
                    cout<<scanner->currentToken().getTokenInfo()<<endl;
                    return false;
                }

            }

      /*  }
        else {
            // Error
            cout<<"Error: expected '=' "<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }*/

    }

    //
    /// CIRCLE
    //
    else if ( scanner->currentToken().getLexem() == "circle" ) {
        // circle = radius:F
        scanner->nextToken();

        if ( scanner->currentToken().getLexem() == "(" ) {
            scanner->nextToken();

            if ( scanner->currentToken().getLexem() == "radius" ) {
                scanner->nextToken();

                shapeType = CIRCLE;

                if ( scanner->currentToken().getLexem() == ":" ) {
                    scanner->nextToken();

 
                    if ( F( shapeData.radious ) ) {

                        if ( scanner->currentToken().getLexem() == ")" ) {
                            scanner->nextToken();
                            return true;
                        }

                        else {
                            // Error
                            cout<<"Error: expected ')' "<<endl;
                            cout<<scanner->currentToken().getTokenInfo()<<endl;
                            return false;
                        }


                    }

                    else return false;

                }
                else {
                    // Error
                    cout<<"Error: expected ':' "<<endl;
                    cout<<scanner->currentToken().getTokenInfo()<<endl;
                    return false;
                }
            }
            else {
                // Error
                cout<<"Error: expected 'radius' "<<endl;
                cout<<scanner->currentToken().getTokenInfo()<<endl;
                return false;
            }

        }
        else {
            // Error
            cout<<"Error: expected ')' "<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }

    }
    // polygon = { VERTICES_LIST }
    else if ( scanner->currentToken().getLexem() == "polygon" ) {
        scanner->nextToken();

        shapeType = POLY;

        if ( scanner->currentToken().getLexem() == "=" ) {
            scanner->nextToken();

            if ( scanner->currentToken().getLexem() == "{" ) {
                scanner->nextToken();


                // if ( VERTICES_LIST ( ... ) )
                if ( scanner->currentToken().getLexem() == "}" ) {
                    scanner->nextToken();
                }
                else {
                    // Error
                    cout<<"Error: expected '}' "<<endl;
                    cout<<scanner->currentToken().getTokenInfo()<<endl;
                    return false;
                }

            }
            else {
                // Error
                cout<<"Error: expected '{' "<<endl;
                cout<<scanner->currentToken().getTokenInfo()<<endl;
                return false;
            }



        }
        else {
            // Error
            cout<<"Error: expected '=' "<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }

    }

    // Defaults
    shapeType = RECT; // type
    shapeData.w = 2.0f;
    shapeData.h = 2.0f;

    return true;
}

bool Parser::VISUAL(VisualData &visualData, xEngine::CoreSystem::Events::VISUAL &visualType) {
    // VISUAL ::= color (BORDER FILL) | texture:filename | e
    if ( scanner->currentToken().getLexem() == "color" ) {
        scanner->nextToken();

        visualType = COLOR;

        if ( scanner->currentToken().getLexem() == "(" ) {
            scanner->nextToken();

            // Create objects
            visualData.border = new Color4;
            visualData.fill = new Color4;

            bool ok = BORDER( *(visualData.border) ) && FILL( *(visualData.fill) );



            if (ok && scanner->currentToken().getLexem() == ")") {
                // OK
                scanner->nextToken();
                return true;
            }
            else {

                // ERROR
                cout<<"Error: expected ')' "<<endl;
                cout<<scanner->currentToken().getTokenInfo()<<endl;
                return false;
            }
        }

    }
    else if ( scanner->currentToken().getLexem() == "image" ) {
        scanner->nextToken();
        
        if ( scanner->currentToken().getLexem() == "(" ) {
            scanner->nextToken();
            
            if ( scanner->currentToken().getLexem() == "texture" ) {
                scanner->nextToken();

                visualType = TEXTURE;

                if ( scanner->currentToken().getLexem() == ":" ) {
                    scanner->nextToken();

                    if ( scanner->currentToken().getType() == IDENTIFICATOR) {

                        visualData.texture = new string( scanner->currentToken().getLexem() );
                        scanner->nextToken();

                        if ( TEX_REPEAT( visualData.repeatX, visualData.repeatY) ) {
                            
                            if ( scanner->currentToken().getLexem() == ")" ) {
                                scanner->nextToken();
                                return true;
                            }
                            else {
                                // ERROR
                                cout<<"Error: expected ')' "<<endl;
                                cout<<scanner->currentToken().getTokenInfo()<<endl;
                                return false;                                
                            }
                                
                        }
                    }
                    else {
                        cout<<"Error, expected VALID texture path"<<endl;
                        cout<<scanner->currentToken().getTokenInfo()<<endl;
                        return false;
                    }


                }
                else {
                    cout<<"Error, expected :"<<endl;
                    cout<<scanner->currentToken().getTokenInfo()<<endl;
                    return false;
                }

            }  
            
        }
        else
        {
            // ERROR
            cout<<"Error: expected '(' "<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;            
        }
    }
        
        
        
    



    visualType = COLOR;
    // Create objects
    visualData.border = new Color4;
    visualData.fill = new Color4;

    visualData.border->set(0.0f, 1.0f, 0.0f, 1.0f);
    visualData.fill->set(0.0f, 0.0f, 1.0f, 0.5f);
    return true; // Empty derivation allowed
}

bool Parser::TEX_REPEAT(float &rX, float &rY) {

    if ( scanner->currentToken().getLexem() == "repeat" ) {
        scanner->nextToken();

        if ( scanner->currentToken().getLexem() == ":" ) {
            scanner->nextToken();

            if ( F( rX ) && F( rY ) )
                return true;
            else
            {
                cout<<"Error, expected X and Y repeat values"<<endl;
                return false;
            }
        }
        else {
            cout<<"Error, expected :"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }

    }

    rX = rY = 1; // Default; no repeat
    return true; // Empty derivation
}

bool Parser::BORDER(Color4 &color4) {
    // BORDER ::= border:COLOR4 | e
    if ( scanner->currentToken().getLexem() == "border" ) {
        scanner->nextToken();

        if ( scanner->currentToken().getLexem() == ":" ) {
            scanner->nextToken();

            return COLOR4( color4 );
        }
        else {
            cout<<"Error, expected :"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }

    }

    color4.set(0.0f, 1.0f, 0.0f, 1.0f);
    return true; // Empty derivation
}

bool Parser::FILL(Color4 &color4) {
    // FILL ::= fill:COLOR4 | e
    //float val;

    if ( scanner->currentToken().getLexem() == "fill" ) {
        scanner->nextToken();

        if ( scanner->currentToken().getLexem() == ":" ) {
            scanner->nextToken();

            return COLOR4( color4 );
        }
        else {
            cout<<"Error, expected :"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }

    }

    color4.set(0.0f, 0.0f, 1.0f, 0.5f);
    return true; // Empty derivation
}

bool Parser::COLOR4(Color4 &color4) {
    // COLOR4 ::= [F F F F]
    float r, g, b, a; // TODO, FIX

    if (scanner->currentToken().getLexem() == "[")
    {
        scanner->nextToken();

        if ( F(r) )
        {
            if ( F(g) )
            {
                if ( F(b) )
                {
                    if ( F(a) )
                    {
                        if (scanner->currentToken().getLexem() == "]")
                        {
                            scanner->nextToken();

                            color4.set(r, g, b, a);
                            return true;
                        }
                        else
                        {
                            // vector must end with ] error
                            cout<<"Error: Vector should end with ]"<<endl;
                            cout<<scanner->currentToken().getTokenInfo()<<endl;
                            return false;
                        }
                    }
                    else {
                        // vector a component error
                        cout<<"Error, color Alpha component missing?"<<endl;
                        cout<<scanner->currentToken().getTokenInfo()<<endl;
                        return false;
                    }
                }
                else
                {
                    // vector z component error
                    cout<<"Error, color Blue component missing?"<<endl;
                    cout<<scanner->currentToken().getTokenInfo()<<endl;
                    return false;
                }
            }
            else
            {
                // vector y component error
                cout<<"Error, color Green component missing?"<<endl;
                cout<<scanner->currentToken().getTokenInfo()<<endl;
                return false;
            }
        }
        else
        {
            // vector x component error
            cout<<"Error, color Red component missing?"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }
    }
    else
    {
        // must start with [ error
        cout<<"Error: Vector should begin with ["<<endl;
        cout<<scanner->currentToken().getTokenInfo()<<endl;
        return false;
    }

    return false;
}


//
// VARIABLES
//
bool Parser::DEFVAR() {
    string id;

 //   if (scanner->currentToken().getLexem() == "def")
 //   {
        // Ok so far.
        //scanner->nextToken();

        if (scanner->currentToken().getLexem() == "var") {
            scanner->nextToken();

             // We expect here uniqe identificator (string). It shouldn't be in symtable yet.
            if ( scanner->currentToken().getType() == IDENTIFICATOR )
            {
                // Ok, we have string, validate it.
                id = scanner->currentToken().getLexem();
                if ( this->symTab.containsSym( id ) ) { // Check sym table if there is entry for this id
                    // IF there is -> ERROR!
                    // Identificator already exists.
                    cout<<"Error, identificator " + id + " already exits."<<endl;
                    return false;
                }

                // Ok, read next.
                scanner->nextToken();

                if (scanner->currentToken().getLexem() == "=")
                {
                    scanner->nextToken();
                    float val;

                    if ( F(val) )
                    {
                        // Everything ok.
                        // Save value in symtab
                        this->symTab.insertSym( id, val );
                        return true;
                    }
                    else
                    {
                        // Expression expected error
                        cout<<"Error: Expression expected!"<<endl;
                        cout<<scanner->currentToken().getTokenInfo()<<endl;
                    }
                }
                else
                {
                    // = expected error
                    cout<<"Parse error, = expected, got " + scanner->currentToken().getLexem() <<endl;
                    cout<<scanner->currentToken().getTokenInfo()<<endl;
                }
            }
        }
 //   }

    return false;
}

bool Parser::UPDATEVAR() {
    string id;

    // Update symbol
    if (scanner->currentToken().getLexem() == "update")
    {
        // Ok so far.
        scanner->nextToken();

        if (scanner->currentToken().getLexem() == "var") {
            scanner->nextToken();

            // We expect here uniqe identificator (string), it should be in symtab already, since we're updating it.
            if ( scanner->currentToken().getType() == IDENTIFICATOR )
            {
                // Ok, we have string, validate it.
                id = scanner->currentToken().getLexem();
                if ( !this->symTab.containsSym( id ) ) { // Check sym table if there is entry for this id

                    // There is no identificator in symtab!
                    cout<<"Error, " + id + " is undefined."<<endl;
                    return false;
                }


                // Ok, read next.
                scanner->nextToken();

                if (scanner->currentToken().getLexem() == "=")
                {
                    scanner->nextToken();
                    float val;

                    if ( F(val) )
                    {
                        // Everything ok.
                        // Update value in symtab
                        this->symTab.updateSym( id, val );
                        return true;
                    }
                    else
                    {
                        // Expression expected error
                        cout<<"Error: Expression expected!"<<endl;
                        cout<<scanner->currentToken().getTokenInfo()<<endl;

            //            return false;
                    }
                }
                else
                {
                    // = expected error
                    cout<<"Parse error, = expected, got " + scanner->currentToken().getLexem() <<endl;
                    cout<<scanner->currentToken().getTokenInfo()<<endl;

            //        return false;
                }
            }


        }

    }

    return false;
}


//
// TRANSFORMATION
//
bool Parser::TRANSFORMATION(TransformationData *&tData) {
    // ::= translate VECTOR | rotate E

    tData = new TransformationData; // DELETE WARNING!

    if (scanner->currentToken().getLexem() == "translate")
    {
        // We are translating.
        tData->metaData = TRANSLATE;
        scanner->nextToken();

        Vector3 *vec = new Vector3();


        if ( VECTOR( vec ) )
        {
            // OK
            tData->data = vec;
            return true;
        }
        else
        {
            // Vector expected error
            cout<<"Error: Vector  expected!"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
        }
    }
    else if (scanner->currentToken().getLexem() == "rotate")
    {
        // We are rotating.
        scanner->nextToken();
        tData->metaData = ROTATE;

        float *val = new float;

        if ( F( *val ) )
        {
            // OK
            tData->data = val;
            return true;
        }
        else
        {
            // Expression expected error
            cout<<"Error: Expression expected!"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
        }
    }

    return false;
}

bool Parser::VECTOR(Vector3 *&vec) { // DELETE WARNING!
    //::= [E E E]
    if (scanner->currentToken().getLexem() == "[")
    {
        scanner->nextToken();

        if (F(vec->x))
        {
            if (F(vec->y))
            {
                if (F(vec->z))
                {
                    if (scanner->currentToken().getLexem() == "]")
                    {
                        scanner->nextToken();
                        return true;
                    }
                    else
                    {
                        // vector must end with ] error
                        cout<<"Error: Vector should end with ]"<<endl;
                        cout<<scanner->currentToken().getTokenInfo()<<endl;
                        return false;
                    }
                }
                else
                {
                    // vector z component error
                    cout<<"Error, vector z component missing?"<<endl;
                    cout<<scanner->currentToken().getTokenInfo()<<endl;
                    return false;
                }
            }
            else
            {
                // vector y component error
                cout<<"Error, vector y component missing?"<<endl;
                cout<<scanner->currentToken().getTokenInfo()<<endl;
                return false;
            }
        }
        else
        {
            // vector x component error
            cout<<"Error, vector x component missing?"<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }
    }
    else
    {
        // must start with [ error
        cout<<"Error: Vector should begin with ["<<endl;
        cout<<scanner->currentToken().getTokenInfo()<<endl;
        return false;
    }

    return false;

}

bool Parser::OBJECT(string &object) {

   // map<string, xEngine::PlatformIndependent::SceneNode*>::iterator it = this->currentObjectsTab->find(scanner->currentToken().getLexem());

    if ( this->objectsTab->containsSym( scanner->currentToken().getLexem() ) ) // Object name found in hash table?
        object = scanner->currentToken().getLexem(); // Found
    else
        return false; // Object not in table, error

    // OK
    scanner->nextToken();
    return true;
}


bool Parser::E(float &val) {
    // ::= T EE
    float tmpVal;
    bool Tovrednoten = T(tmpVal);

	return Tovrednoten && EE(  val, tmpVal );
}

bool Parser::EE(float &val, float inVal) {
    // ::=  OP_1 T EE | empty

    OP op;

    if ( OP_1(op) ) // Do we have first class operator at input?
    {
		float Tval = 0.0f;
		bool Tovrednoten = T( Tval );

		if ( op == ADD )
            return Tovrednoten && EE( val,  Tval + inVal );
        else if ( op == SUB )
            return Tovrednoten && EE( val,  Tval - inVal );
        else return false;
    }
	else {
        // Empty derivation allowed
        val = inVal;
		return true;
	}
}

bool Parser::T(float &val){
    // ::= F TT

    float Fval = 0.0f;
    bool Fovrednoten = F( Fval );

    // T.val = TT.val
    // TT.inVal = F.val
	return Fovrednoten && TT( val, Fval);
}

bool Parser::TT(float &val, float inVal) {
    //::= OP_2 F TT | empty

    OP op;

    if ( OP_2(op) ) // Do we have first class operator at input?
    {
		float Tval = 0.0f;
		bool Tovrednoten = T( Tval );

		if ( op == MUL )
            return Tovrednoten && EE( val,  Tval * inVal );
        else if ( op == DIV )
            return Tovrednoten && EE( val,  Tval / inVal );
        else return false;
    }
	else {
        // empty derivation allowed
        val = inVal;
		return true;
	}
}


bool Parser::F(float &val) {
    //::= (E) | number | identificator | FUNC(E)

    //
    // (E)
    //
    if ( scanner->currentToken().getLexem() == "(" ) {
        scanner->nextToken();

        bool tmpE = E(val);

		if (tmpE && scanner->currentToken().getLexem() == ")") {
		    // OK
			scanner->nextToken();
			return true;
		}
		else {

            // ERROR
            cout<<"Error: expected ')' "<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
		}
    }


    //
    // number
    //

    else if ( scanner->currentToken().getType() == INTEGER )
    {
        // It is number and that's ok.

        val = (float) atof( scanner->currentToken().getLexem().c_str()  ); // Evaluate number
        scanner->nextToken();

        return true;
    }
    else if ( scanner->currentToken().getLexem() == "-" ) {
        scanner->nextToken();

        if ( scanner->currentToken().getType() == INTEGER ) {
            val =  -(float) atof( scanner->currentToken().getLexem().c_str()  );
            scanner->nextToken();

            return true;
        }
        else if ( F(val) ) {
            val = -val;
            return true;
        }

        cout<<"Error: float value expected after '-' "<<endl;
        cout<<scanner->currentToken().getTokenInfo()<<endl;
        return false;
    }

    //
    // identificator
    //
    else if ( scanner->currentToken().getType() == IDENTIFICATOR )
    {
        // We have got string, check in sym table if it has been declared
        string *id = &scanner->currentToken().getLexem();
        if ( this->symTab.containsSym( *id ))
            // ok :)
            val = this->symTab.getSymValue( *id );

        // if it wasn't -> ERROR
        else
        {
            cout<<"Error, identificator " + *id + " has not been declared."<<endl;
            return false;
        }


        // if it was
        scanner->nextToken();
        return true;
    }

    //
    // FUNC( E )
    //
    else if ( FUNC(val) ) // Check and evaluate FUNC
        return true;


    // In any other case, parsing failed.
    return false;
}


bool Parser::OP_1(OP &op) {
    //::= +|-
    if (scanner->currentToken().getLexem() == "+" )
    {
        op = ADD;
        scanner->nextToken();
        return true;
    }
    else if ( scanner->currentToken().getLexem() == "-")
    {
        op = SUB;
        scanner->nextToken();
        return true;
    }

    return false;
}

bool Parser::OP_2(OP &op) {
    //::= *|/
    if (scanner->currentToken().getLexem() == "*" )
    {
        op = MUL;
        scanner->nextToken();
        return true;
    }
    else if ( scanner->currentToken().getLexem() == "/")
    {
        op = DIV;
        scanner->nextToken();
        return true;
    }

    return false;
}

bool Parser::FUNC(float &val) {
    //::= sin | cos | exp | sqrt | tan | log

   if ( scanner->currentToken().getType() == STRING ) {
        string token = scanner->currentToken().getLexem();


        scanner->nextToken();

        if ( scanner->currentToken().getLexem() == "(" ) {
            scanner->nextToken();

            // Evaluate E
            float Eval = 0.0f;
            bool tmpE = E(Eval);

            // Apply function on value calculated by E
            // sin, cos, abs
            if ( token == "sin"  ) {
                val = sin(Eval);
            }
            else if ( token == "cos"  ) {
                val = cos(Eval);
            }
            else if ( token == "abs"  ) {
                val = abs(Eval);
            }
            else if ( token == "sqrt"  ) {
                val = sqrt(Eval);
            }
            else if ( token == "tan"  ) {
                val = sqrt(Eval);
            }
            else if ( token == "exp"  ) {
                val = exp(Eval);
            }
            else if ( token == "log"  ) {
                val = log(Eval);
            }


            if (tmpE && scanner->currentToken().getLexem() == ")") {
                // OK
                scanner->nextToken();
                return true;
            }
            else {

                // ERROR
                cout<<"Error: expected ')' "<<endl;
                cout<<scanner->currentToken().getTokenInfo()<<endl;
                return false;
            }
        }
        else {
            cout<<"Error: expected '(' "<<endl;
            cout<<scanner->currentToken().getTokenInfo()<<endl;
            return false;
        }
    }

    return false; // Not an function
}

